package net.youyi.crazycopyer.widget;

import android.content.Context;
import android.renderscript.Matrix2f;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v4.widget.ScrollerCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

/**
 * Created by xzp on 15/11/10.
 */
@CoordinatorLayout.DefaultBehavior(HeaderScrollView.HeaderBehavior.class)
public class HeaderScrollView extends NestedScrollView{
    private int mMaxOffset;
    private int mLastHeight;
    public HeaderScrollView(Context context) {
        super(context);
    }

    public HeaderScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HeaderScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        ViewGroup child= (ViewGroup) getChildAt(0);
        mMaxOffset=-child.getChildAt(0).getMeasuredHeight();
        mLastHeight=child.getChildAt(1).getMeasuredHeight();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        ViewGroup child= (ViewGroup) getChildAt(0);
        mMaxOffset=-child.getChildAt(0).getMeasuredHeight();
        mLastHeight=child.getChildAt(1).getMeasuredHeight();
    }

    public int getMaxOffset(){
        return mMaxOffset;
    }
    public int getLastHeight(){
        return mLastHeight;
    }
    public static class HeaderBehavior extends CoordinatorLayout.Behavior<HeaderScrollView>{
        private int mOffset;
        private Runnable mFlingRunnable;
        private ScrollerCompat mScroller;
        public HeaderBehavior() {
            mOffset=0;
        }

        public HeaderBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
            mOffset=0;
        }

        @Override
        public boolean onLayoutChild(CoordinatorLayout parent, HeaderScrollView child, int layoutDirection) {
            parent.onLayoutChild(child, layoutDirection);
            child.offsetTopAndBottom(mOffset);
            return true;
        }

        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, HeaderScrollView child, View directTargetChild, View target, int nestedScrollAxes) {
            if (mFlingRunnable != null) {
                child.removeCallbacks(mFlingRunnable);
            }
            return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
        }

        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, HeaderScrollView child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
            super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
            int consumedY=getConsumeY(child,dyUnconsumed);
            //mOffset-=consumedY;
            offsetChild(coordinatorLayout,-consumedY);
        }

        @Override
        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, HeaderScrollView child, View target, int dx, int dy, int[] consumed) {
            if(dy<0){
                if(target.canScrollVertically(-1)){
                    return;
                }
                else {
                    int consumedY=getConsumeY(child,dy);
                    consumed[1]=consumedY;
                  //  mOffset-=consumedY;
                    offsetChild(coordinatorLayout, -consumedY);
                }
            }else {
                int consumedY=getConsumeY(child,dy);
                consumed[1]=consumedY;
              //  mOffset-=consumedY;
                offsetChild(coordinatorLayout,-consumedY);
            }
        }
        private int getConsumeY(HeaderScrollView scrollView,int dy) {
//        if(offset==maxOffset)
//            return 0;
            if(dy==0)
                return 0;
            int consumeY=dy;
            int tempOffset=mOffset-dy;
            int maxOffset=scrollView.getMaxOffset();
            if(tempOffset<maxOffset){
                consumeY=mOffset-maxOffset;
            }else if(tempOffset>0){
                consumeY=mOffset;
            }
            return consumeY;
        }
        public int getOffset(){
            return mOffset;
        }
        private void offsetChild(CoordinatorLayout coordinatorLayout,int offset){
            if(offset==0)
                return;
            mOffset+=offset;
            int count=coordinatorLayout.getChildCount();
            for(int i=0;i<count;i++){
                coordinatorLayout.getChildAt(i).offsetTopAndBottom(offset);
            }
        }
        @Override
        public boolean onNestedFling(CoordinatorLayout coordinatorLayout, HeaderScrollView child, View target, float velocityX, float velocityY, boolean consumed) {
          //  return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
            if(!consumed){
                return fling(coordinatorLayout,child,velocityY);
            }
            return false;
        }

        @Override
        public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, HeaderScrollView child, View target, float velocityX, float velocityY) {
            if(velocityY<0){
                if(target.canScrollVertically(-1)){
                    return false;
                }
                else {
                    return fling(coordinatorLayout,child,velocityY);
                }
            }
            else{
                if(mOffset>child.getMaxOffset()){
                    return fling(coordinatorLayout,child,velocityY);
                }else {
                    return false;
                }
            }
        }
        private boolean fling(CoordinatorLayout parent, HeaderScrollView child, float velocityY) {
            if (mFlingRunnable != null) {
                child.removeCallbacks(mFlingRunnable);
            }

            if (mScroller == null) {
                mScroller = ScrollerCompat.create(child.getContext());
            }

            mScroller.fling(
                    0, child.getTop(),
                    0, -Math.round(velocityY),
                    0, 0,
                    child.getMaxOffset(), 0);

            if (mScroller.computeScrollOffset()) {
                mFlingRunnable = new FlingRunnable(parent, child);
                ViewCompat.postOnAnimation(child, mFlingRunnable);
                return true;
            } else {
                mFlingRunnable = null;
                return false;
            }
        }
        private class FlingRunnable implements Runnable {
            private final CoordinatorLayout mParent;
            private final HeaderScrollView mScrollView;
            FlingRunnable(CoordinatorLayout parent, HeaderScrollView scrollView) {
                mParent = parent;
                mScrollView = scrollView;
            }

            @Override
            public void run() {
                if (mScrollView != null && mScroller != null && mScroller.computeScrollOffset()) {
                    int delta = mScroller.getCurrY() - mScrollView.getTop();
                  //  Log.e("delta",delta+","+mScrollView.getTop()+","+mScroller.getCurrY());
                    offsetChild(mParent,delta);
                    // Post ourselves so that we run on the next animation
                    ViewCompat.postOnAnimation(mScrollView, this);
                }
            }
        }
    }
    public static class ScrollViewBehavior extends CoordinatorLayout.Behavior<View>{
        public ScrollViewBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
            return dependency instanceof HeaderScrollView;
        }

        @Override
        public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
            //return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
            List<View> list=parent.getDependencies(child);
            int offset=0;
            for(int i=0;i<list.size();i++){
                if(list.get(i) instanceof HeaderScrollView){
                    HeaderScrollView scrollView= (HeaderScrollView) list.get(i);
                    offset=scrollView.getLastHeight();
                    break;
                }
            }
            final int measuredHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec) - heightUsed- offset;
            int childMeasureSpec = View.MeasureSpec.makeMeasureSpec(measuredHeight, View.MeasureSpec.EXACTLY);
            child.measure(parentWidthMeasureSpec,childMeasureSpec);
            return true;
        }

        @Override
        public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
            List<View> list=parent.getDependencies(child);
           // int offset=0;
            int top=0;
            for(int i=0;i<list.size();i++){
                if(list.get(i) instanceof HeaderScrollView){
                    HeaderScrollView scrollView= (HeaderScrollView) list.get(i);
//                    CoordinatorLayout.LayoutParams lp= (CoordinatorLayout.LayoutParams) scrollView.getLayoutParams();
//                    HeaderBehavior behavior= (HeaderBehavior) lp.getBehavior();
                    top=scrollView.getBottom();
                   // offset=behavior.getOffset();
                    break;
                }
            }
            child.layout(0,top,child.getMeasuredWidth(),top+child.getMeasuredHeight());
           // child.offsetTopAndBottom(offset);
            return true;
        }
    }
}
